package main

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"
)

var (
	rWg    sync.WaitGroup
	wWg    sync.WaitGroup
	wg     sync.WaitGroup
	ctx    context.Context
	cancel context.CancelFunc
	textCh = make(chan string, 10000)
)

func init() {
	wg.Add(4) //创建4个协程,1个接收信号,3个处理业务
	ctx, cancel = context.WithCancel(context.Background())
}

func listenSignal() {
	defer wg.Done()
	ch := make(chan os.Signal)                         //存放信号的通道
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) //接收信号
	for {
		select {
		case sg := <-ch:
			fmt.Printf("got the signal %d\n", sg)
			cancel() //取消，通知用到ctx的所有协程
			return
		case <-ctx.Done():
			return
		}
	}
}

func readFile(infile string) {
	defer rWg.Done()
	if fin, err := os.Open(infile); err != nil {
		log.Fatalln(err)
	} else {
		defer fin.Close()
		reader := bufio.NewReader(fin)
		for {
			line, _, err := reader.ReadLine()
			if err != nil {
				if err == io.EOF {
					break
				} else {
					log.Fatalln(err)
				}
			}
			fmt.Println("Reading......")
			textCh <- string(line)
		}
	}
}

func writeFile(outfile string) {
	defer wWg.Done()
	fout, err := os.Create(outfile)
	if err != nil {
		log.Fatalln(err)
	}
	defer fout.Close()
	writer := bufio.NewWriter(fout)
LOOP:
	for {
		select {
		case <-ctx.Done():
			return
		case line, ok := <-textCh:
			if !ok {
				break LOOP
			}
			fmt.Println("Writing......")
			writer.WriteString(line)
			writer.WriteString("\n")
		}
	}
	writer.Flush()
}

func main() {
	go listenSignal()
	rWg.Add(3)
	go readFile("file1.txt")
	go readFile("file2.txt")
	go readFile("file3.txt")
	wWg.Add(1)
	go writeFile("file.txt")
	rWg.Wait()
	close(textCh)
	wWg.Wait()
}
